package biz.datalk.industrialland.common.encrypt.sm;

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;

import java.util.Arrays;

/**
 * <a href="http://gmssl.org/docs/sm3.html">GmSSL SM3</a>
 *
 * <pre>
 * echo -n 'abc' | gmssl dgst -sm3
 * echo -n 'abc' | gmssl dgst -sm3 -hmac '123456'
 * echo -n '中文' | gmssl dgst -sm3 -hmac 'qwe123!@#'
 * </pre>
 *
 * org.bouncycastle:bcprov-jdk15on:1.70
 *
 * @author tarofang@163.com
 * @date 2022-06-23
 */
public class SM3Util extends GMBaseUtil {

    /**
     * SM3 散列
     *
     * @param srcData 原始数据的 byte 数组
     *
     * @return SM3 结果
     *
     * @author tarofang@163.com
     * @date 2022年06月23日
     */
    public static byte[] hash(byte[] srcData) {
        SM3Digest digest = new SM3Digest();
        digest.update(srcData, 0, srcData.length);
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash, 0);
        return hash;
    }

    /**
     * SM3 散列值校验
     *
     * @param srcData 原始数据的 byte 数组
     * @param sm3Hash SM3 散列的 byte 数组
     *
     * @return true-校验通过 false-校验不通过
     *
     * @author tarofang@163.com
     * @date 2022年06月23日
     */
    public static boolean verify(byte[] srcData, byte[] sm3Hash) {
        byte[] newHash = hash(srcData);
        return Arrays.equals(newHash, sm3Hash);
    }

    /**
     * HMAC-SM3
     *
     * @param srcData 原始数据的 byte 数组
     * @param key     散列 KEY 的 byte 数组
     *
     * @return HMAC-SM3 计算结果
     *
     * @author tarofang@163.com
     * @date 2022年06月23日
     */
    public static byte[] hmac(byte[] srcData, byte[] key) {
        KeyParameter keyParameter = new KeyParameter(key);
        SM3Digest digest = new SM3Digest();
        HMac mac = new HMac(digest);
        mac.init(keyParameter);
        mac.update(srcData, 0, srcData.length);
        byte[] result = new byte[mac.getMacSize()];
        mac.doFinal(result, 0);
        return result;
    }

    /**
     * HMAC-SM3 校验
     *
     * @param srcData 原始数据的 byte 数组
     * @param key     散列 KEY 的 byte 数组
     * @param sm3Hmac HMAC-SM3 的 byte 数组
     *
     * @return true-校验通过 false-校验不通过
     *
     * @author tarofang@163.com
     * @date 2022年06月23日
     */
    public static boolean verifyHmac(byte[] srcData, byte[] key, byte[] sm3Hmac) {
        byte[] newHmac = hmac(srcData, key);
        return Arrays.equals(newHmac, sm3Hmac);
    }
}
